global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M7_ReadCR3_S6_00000B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M8_WriteCR3_S8_0001010B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M7_ReadCR2_S6_00000B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M8_WriteCR2_S8_0001010B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M7_ReadCR4_S6_00000B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M8_WriteCR4_S8_0001010B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M7_ReadCR0_S6_00000B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M8_WriteCR0_S8_0001010B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M4_Lidt_S10_0002010B07
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M3_Ltr_S8_0001010B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M10_WriteMxcsr_S8_00010109
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M9_ReadMxcsr_S6_000009
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M6__Cpuid_S12_000201090F09
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M6_GetRBP_S6_00000B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M5_RdMsr_S8_00010B09
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M5_RdTsc_S6_00000B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M3_Sti_S6_000001
global _m5_tysos_N3_ABI_T16_MemoryOperations_Special_M19_QuickClearAligned16_S10_0002010B0B
global _m5_tysos_N3_ABI_T15_OtherOperations_Special_M11_switch_task_S12_0002010F0B0B

global _m8_mscorlib_N6_System_T4_Math_S6_1284BC_M5_Round_S8_00010D0D

global __memcpy
global __memmove

global _conv_u8_r8

extern __display_halt
extern __undefined_func

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M7_ReadCR3_S6_00000B:
	mov	rax, cr3
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M8_WriteCR3_S8_0001010B:
	mov rax, [rsp + 8]
	mov cr3, rax
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M7_ReadCR0_S6_00000B:
	mov	rax, cr0
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M8_WriteCR0_S8_0001010B:
	mov rax, [rsp + 8]
	mov cr0, rax
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M7_ReadCR2_S6_00000B:
	mov	rax, cr2
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M8_WriteCR2_S8_0001010B:
	mov rax, [rsp + 8]
	mov cr2, rax
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M7_ReadCR4_S6_00000B:
	mov	rax, cr4
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M8_WriteCR4_S8_0001010B:
	mov rax, [rsp + 8]
	mov cr4, rax
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M4_Lidt_S10_0002010B07:
	push rbp
	mov rbp, rsp

	sub rsp, 0x10
	
	mov rax, [rbp + 16]
	mov rbx, rax

	shr rbx, 48
	shl rax, 16
	add rax, [rbp + 24]

	mov [rsp], rax
	mov [rsp + 8], rbx

	lidt [rsp]

	leave
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M3_Ltr_S8_0001010B:
	ltr [rsp + 8]
	ret

_m5_tysos_N3_ABI_T16_MemoryOperations_Special_M19_QuickClearAligned16_S10_0002010B0B:
	push rbp
	mov rbp, rsp

	mov	rdi, [rbp + 16]
	mov rcx, [rbp + 24]

	shr rcx, 4

	sub rsp, 16
	mov rax, 0x0
	mov [rsp], rax
	mov [rsp + 8], rax

	movdqu	xmm0, [rsp]

.doloop:
	movdqa	[rdi], xmm0
	add	rdi, 16
	loop .doloop
	
	leave
	ret
	
__memcpy:
	push rbp
	mov rbp, rsp

	mov rdi, [rbp + 16]
	mov rsi, [rbp + 24]
	mov ecx, [rbp + 32]

	rep movsb

	leave
	ret

__memmove:
	push rbp
	mov rbp, rsp

	mov rdi, [rbp + 16]
	mov rsi, [rbp + 24]
	mov ecx, [rbp + 32]
	
	cmp rdi, rsi
	ja .domove

	rep movsb
	leave
	ret

.domove:
	add rdi, rcx
	add rsi, rcx

	cmp rcx, 0
	jne .doloop

	leave
	ret

.doloop:
	dec rdi
	dec rsi
	
	mov byte al, [rsi]
	mov byte [rdi], al
	loop .doloop

	leave
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M11_switch_task_S12_0002010F0B0B:
	; return rip is pushed by the call instruction
	pushfq
	push rax
	push rbx
	push rcx
	push rdx
	push rsi
	push rdi
	push rbp
	push r8
	push r9
	push r10
	push r11
	push r12
	push r13
	push r14
	push r15

	; store the old rsp pointer and new rsp value
	mov rbx, [rsp + 144]
	mov rax, [rsp + 136]

	; store the old rsp if the pointer is valid
	cmp rax, 0
	je .dontsave
	mov [rax], rsp
.dontsave:

	; switch to the new stack
	mov rsp, rbx

	; restore saved registers
	pop r15
	pop r14
	pop r13
	pop r12
	pop r11
	pop r10
	pop r9
	pop r8
	pop rbp
	pop rdi
	pop rsi
	pop rdx
	pop rcx
	pop rbx
	pop rax
	popfq

	; ret to restore rip
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M6_GetRBP_S6_00000B:
	mov rax, rbp
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M10_WriteMxcsr_S8_00010109:
	ldmxcsr [rsp + 8]
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M9_ReadMxcsr_S6_000009:
	sub rsp, 8
	stmxcsr [rsp]
	mov dword eax, [rsp]
	add rsp, 8
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M6__Cpuid_S12_000201090F09:
	; void _Cpuid(uint req_no, uint *buf)

	xor rcx, rcx
	mov dword eax, [rsp + 8]
	cpuid
	
	mov rdi, [rsp + 16]
	mov dword [rdi], eax
	mov dword [rdi + 4], ebx
	mov dword [rdi + 8], ecx
	mov dword [rdi + 12], edx

	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M5_RdMsr_S8_00010B09:
	; static ulong RdMsr(uint reg_no)
	mov dword ecx, [rsp + 8]
	rdmsr
	sub rsp, 8
	mov dword [rsp], eax
	mov dword [rsp + 4], edx
	mov qword rax, [rsp]
	add rsp, 8
	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M5_RdTsc_S6_00000B:
	rdtsc
	sub rsp, 8
	mov dword [rsp], eax
	mov dword [rsp + 4], edx
	mov qword rax, [rsp]
	add rsp, 8
	ret

_conv_u8_r8:
	push qword [rsp]
	call __undefined_func
	call __display_halt
.haltloop:
	xchg bx, bx
	hlt
	jmp .haltloop

_m8_mscorlib_N6_System_T4_Math_S6_1284BC_M5_Round_S8_00010D0D:
	; rely on the mxcsr rounding mode being round-to-even (set up in Arch)

	cvtsd2si	rax, [rsp + 8]
	cvtsi2sd	xmm0, rax

	ret

_m5_tysos_N3_ABI_T15_OtherOperations_Special_M3_Sti_S6_000001:
	sti
	ret

